package com.harry.utility;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import com.harry.configuration.ConstSettings;
import com.harry.decoupling.defi.proxy.GenericSrvProxy;
import com.harry.decoupling.defi.tool.DataExchange;
import com.harry.resource.workflow.entity.WorkFlowInstance;
import com.harry.resource.workflow.entity.WorkFlowVariable;
import com.harry.resource.workflow.entity.WorkRoute;
import com.harry.utility.query.InnerCriteria;

public class WorkFlowHelper {

	public static Object readFromVariable(WorkFlowInstance flowInstance, String property) throws Exception {
		Map<String, WorkFlowVariable> variableMap = findWorkVariableMap(flowInstance);
		String[] properties = PoEntityHelper.splitProperties(property);
		String propertyRootFrom = properties[0];
		String propertyPathTo = StringUtils.join(ArrayUtils.subarray(properties, 1, properties.length), ".");
		WorkFlowVariable variable = (WorkFlowVariable) variableMap.get(propertyRootFrom);
		if (variable == null) {
			return null;
		} else {
			Object root = srv().one(ConstSettings.URsrcEntityMap.get(variable.getEntityType()), variable.getIdentity());
			return PoEntityHelper.readValueByProperty(root, propertyPathTo);
		}
	}

	public static WorkFlowVariable findVariableByProperty(WorkFlowInstance flowInstance, String property) throws Exception {
		Map<String, WorkFlowVariable> variableMap = findWorkVariableMap(flowInstance);
		String[] properties = PoEntityHelper.splitProperties(property);
		String key = properties[0];
		return WorkFlowVariable.class.cast(variableMap.get(key));
	}

	public static Map<String, WorkFlowVariable> findWorkVariableMap(WorkFlowInstance flowInstance) throws Exception {
		Map<String, Object> map = InnerUtils.list2map(PoEntityHelper.loadMany(WorkFlowInstance.class, flowInstance.getId(), "flowVariables"), o -> WorkFlowVariable.class.cast(o).getProperty());
		Map<String, WorkFlowVariable> variableMap = new LinkedHashMap<>();
		for (Entry<String, Object> entry : map.entrySet()) {
			variableMap.put(entry.getKey(), (WorkFlowVariable) entry.getValue());
		}
		return variableMap;
	}

	public static Map<String, Object> findRealVariableMap(Map<String, WorkFlowVariable> workVariableMap) throws Exception {
		Map<String, Object> map = InnerUtils.mapObject();
		for (Entry<String, WorkFlowVariable> entry : workVariableMap.entrySet()) {
			WorkFlowVariable variable = entry.getValue();
			Object obj = srv().one(ConstSettings.URsrcEntityMap.get(variable.getEntityType()), variable.getIdentity());
			map.put(variable.getProperty(), obj);
		}
		return map;
	}

	public static boolean doesRouteMatch(WorkFlowInstance flowInstance, WorkRoute route) throws Exception {
		Map<String, Object> realVariableMap = findRealVariableMap(findWorkVariableMap(flowInstance));
		Object jsonCriteria = PoEntityHelper.parseJSEL(realVariableMap, (String) PoEntityHelper.readValueByProperty(route, "targetCriteria"));
		return srv().countByCriteria(WorkRoute.class, de().parse(jsonCriteria, InnerCriteria.class)) != 0;
	}

	private static DataExchange de() {
		return BeanCtxUtils.getBeanByType(DataExchange.class);
	}

	private static GenericSrvProxy srv() {
		return BeanCtxUtils.getBeanByType(GenericSrvProxy.class);
	}
}
